/**
 * Project litesql++
 */


#include "sqlite_db.h"
#include "log.h"

/**
 * SQLiteDB implementation
 */

SQLiteDB::SQLiteDB() : sqlite3_handler_(nullptr) { }

SQLiteDB::~SQLiteDB() {
    if (sqlite3_handler_) {
        sqlite3_close(sqlite3_handler_);
    }
}

SQLiteDB::SQLiteDB(const string &db_file) {
    Open(db_file);
}
/**
 * @param db_file
 * @return const int
 */
const int SQLiteDB::Open(const string& db_file) {

    return sqlite3_open(db_file.c_str(), &sqlite3_handler_);
}

/**
 * @param sqlite_table
 * @return const int
 */
const int SQLiteDB::Create(const SQLiteTable& sqlite_table) {
    string sql_statement = "CREATE TABLE IF NOT EXISTS " + sqlite_table.table_name() + "("
    + sqlite_table.ColumnsAsSQLCreateString() + ")";
    return ExecSQL(sql_statement);
}

/**
 * @param table_name
 * @param columns
 * @return const int
 */
const int SQLiteDB::Create(const string& table_name, const string& columns) {
    string sql_statement = "CREATE TABLE IF NOT EXISTS " + table_name + "(" + columns + ")";

    return ExecSQL(sql_statement);
}

/**
 * @param table_name
 * @return const int
 */
const int SQLiteDB::Insert(const string& table_name, const ContentValues& values) {
    string sql_statement = "INSERT INTO " + table_name + " " + values.ValuesAsSQLInsertString();

    return ExecSQL(sql_statement);
}

/**
 * @param table_name
 * @param values
 * @param where_condition
 * @return const int
 */
const int SQLiteDB::Update(const string& table_name, const ContentValues& values, const string& where_condition) {
    string sql_statement = "UPDATE " + table_name + " SET " + values.ValuesAsSQLUpdateString() + " " + where_condition;

    return ExecSQL(sql_statement);
}

/**
 * @param table_name
 * @param where_condition
 * @return const int
 */
const int SQLiteDB::Delete(const string& table_name, const string& where_condition) {
    string sql_statement = "DELETE FROM " + table_name + " "  + where_condition;

    return ExecSQL(sql_statement);
}

/**
 * @param statement
 * @return const int
 */
const int SQLiteDB::ExecSQL(const string& statement) {

    char* errmsg;
    int rc = sqlite3_exec(sqlite3_handler_, statement.c_str(), nullptr, nullptr, &errmsg);

    if (rc) {
        LOGE("%s, return %s", errmsg, SQLiteCodeAsString(rc).c_str());
    }

    return rc;
}

/**
 * @return const int
 */
const int SQLiteDB::Begin() {
    return ExecSQL("BEGIN");
}

/**
 * @return const int
 */
const int SQLiteDB::Commit() {
    return ExecSQL("COMMIT");
}

/**
 * @return const int
 */
const int SQLiteDB::RollBack() {
    return ExecSQL("ROLLBACK");
}

const string SQLiteDB::SQLiteCodeAsString(int error_code) {
    switch (error_code)
    {
        case SQLITE_OK              : return "SQLITE_OK";
        case SQLITE_ERROR           : return "SQLITE_ERROR";
        case SQLITE_INTERNAL        : return "SQLITE_INTERNAL";
        case SQLITE_PERM            : return "SQLITE_PERM";
        case SQLITE_ABORT           : return "SQLITE_ABORT";
        case SQLITE_BUSY            : return "SQLITE_BUSY";
        case SQLITE_LOCKED          : return "SQLITE_LOCKED";
        case SQLITE_NOMEM           : return "SQLITE_NOMEM";
        case SQLITE_READONLY        : return "SQLITE_READONLY";
        case SQLITE_INTERRUPT       : return "SQLITE_INTERRUPT";
        case SQLITE_IOERR           : return "SQLITE_IOERR";
        case SQLITE_CORRUPT         : return "SQLITE_CORRUPT";
        case SQLITE_NOTFOUND        : return "SQLITE_NOTFOUND";
        case SQLITE_FULL            : return "SQLITE_FULL";
        case SQLITE_CANTOPEN        : return "SQLITE_CANTOPEN";
        case SQLITE_PROTOCOL        : return "SQLITE_PROTOCOL";
        case SQLITE_EMPTY           : return "SQLITE_EMPTY";
        case SQLITE_SCHEMA          : return "SQLITE_SCHEMA";
        case SQLITE_TOOBIG          : return "SQLITE_TOOBIG";
        case SQLITE_CONSTRAINT      : return "SQLITE_CONSTRAINT";
        case SQLITE_MISMATCH        : return "SQLITE_MISMATCH";
        case SQLITE_MISUSE          : return "SQLITE_MISUSE";
        case SQLITE_NOLFS           : return "SQLITE_NOLFS";
        case SQLITE_AUTH            : return "SQLITE_AUTH";
        case SQLITE_FORMAT          : return "SQLITE_FORMAT";
        case SQLITE_RANGE           : return "SQLITE_RANGE";
        case SQLITE_NOTADB          : return "SQLITE_NOTADB";
        case SQLITE_NOTICE          : return "SQLITE_NOTICE";
        case SQLITE_WARNING         : return "SQLITE_WARNING";
        case SQLITE_ROW             : return "SQLITE_ROW";
        case SQLITE_DONE            : return "SQLITE_DONE";
        default                     : return "UNKNOWN_ERROR";
    }
}





